package com.yunji.storage.business;

import com.yunji.base.cache.BaseCache;
import com.yunji.base.domain.BelongDO;
import com.yunji.base.enums.AuditStatus;
import com.yunji.base.enums.SystemName;
import com.yunji.base.service.BelongService;
import com.yunji.common.base.BaseBusiness;
import com.yunji.common.constant.LogicCode;
import com.yunji.common.enums.business.StorageStatus;
import com.yunji.common.enums.business.StorageType;
import com.yunji.common.enums.common.ErrorEnum;
import com.yunji.common.model.dto.LoginInfo;
import com.yunji.common.utils.DecimalUtils;
import com.yunji.common.utils.TimeUtils;
import com.yunji.common.utils.bean.BeanUtils;
import com.yunji.common.utils.uuid.UUIDUtils;
import com.yunji.storage.bo.RepairInfoListQueryBO;
import com.yunji.storage.bo.RepairRemoveBO;
import com.yunji.storage.bo.RepairSelectQueryBO;
import com.yunji.storage.bo.StorageUpdateAuditBO;
import com.yunji.storage.consumer.StockConsumer;
import com.yunji.storage.domain.*;
import com.yunji.storage.dto.*;
import com.yunji.storage.enums.*;
import com.yunji.storage.provide.StockProvide;
import com.yunji.storage.service.*;
import com.yunji.storage.vo.RepairTicketVO;
import com.yunji.system.service.TokenService;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @Project: yunji-coffee
 * @Package: com.yunji.storage.business
 * @Title: RepairTicketBusiness
 * <p>
 * History:
 * Date                     Version     Author          Summary
 * ============================================================
 * 2024-08-27 19:54:25      V1.0        HuaAo       新建类
 */
@Component
public class RepairTicketBusiness extends BaseBusiness {

    @Resource
    StorageBusiness business;

    @Resource
    IDiscardTicketService discardTicketService;

    @Resource
    IDiscardInfoService discardInfoService;

    @Resource
    BelongService belongService;

    @Resource
    IRepairTicketService repairTicketService;

    @Resource
    IStorageTicketService storageTicketService;

    @Resource
    IStorageRecordsService storageRecordsService;

    @Resource
    StorageInteractBusiness interactBusiness;

    @Resource
    StockConsumer stockConsumer;

    @Resource
    IRepairInfoService repairInfoService;

    @Resource
    StockProvide stockProvide;

    @Resource
    TokenService tokenService;

    /**
     * 新增坏返单
     *
     * @param dto
     */
    @Transactional
    public Long create(RepairTicketDTO dto) {
        logs.info("【新增坏返单】坏返信息:{}", dto);
        checkRepairTicket(dto);

        LoginInfo user = tokenService.getUser();
        Long belongId = user.getBelongId();
        Assert.isTrue(BeanUtils.isNotNull(belongId), ErrorEnum.BUSINESS_121003.getText());
        logs.info("【新增坏返单】当前用户所属ID:{}", belongId);


        BelongDO vo = BaseCache.getBelong(belongId);
        logs.info("【新增坏返单】当前用户所属信息:{}", vo);
        Assert.isTrue(BeanUtils.isNotNull(vo), ErrorEnum.BUSINESS_121004.getText());

        RepairTicketDO repairTicket = new RepairTicketDO();
        BeanUtils.clone(dto, repairTicket);
        repairTicket.setBelongId(belongId);
        repairTicket.setApplyId(user.getUserId());
        repairTicket.setApplyName(user.getNickname());
        repairTicket.setApplyBelongId(belongId);
        repairTicket.setApplyBelongName(vo.getBelongName());


        String repairCode = UUIDUtils.repairCode();
        logs.info("【新增坏返单】调拨单号:{}", repairCode);
        repairTicket.setRepairStatus(RepairStatus.COMMIT.getCode());
        Date time = TimeUtils.getNowDate();
        logs.info("【新增坏返单】提交时间:{}", time);
        repairTicket.setApplyTime(time);

        repairTicket.setCreateTime(time);
        repairTicket.setRepairCode(repairCode);
        Assert.isTrue(repairTicketService.create(repairTicket), "新增失败");
        StorageUpdateAuditBO auditBO = new StorageUpdateAuditBO();
        auditBO.setBusinessId(repairTicket.getRepairId());
        auditBO.setAuditStatus(AuditStatus.WAIT.getCode());
        repairTicketService.updateAuditStatus(auditBO);

        //处理调拨详情
        handleInfoList(repairTicket, dto.getInfoList(), true);

        return repairTicket.getRepairId();
    }

    /**
     * 坏返单详情
     *
     * @param repairId
     * @return
     */
    public RepairTicketVO select(Long repairId) {
        RepairTicketVO vo = new RepairTicketVO();
        RepairTicketDO ticket = repairTicketService.select(repairId);
        if (BeanUtils.isNull(vo)) return null;
        BeanUtils.clone(ticket, vo);
        vo.setOutBelongName(BaseCache.getBelongName(vo.getOutBelongId()));
        vo.setParentId(BaseCache.getBelong(vo.getBelongId()).getParentId());
        if (BeanUtils.isNotNull(vo.getIntoBelongId())){
            vo.setIntoBelongName(BaseCache.getBelongName(vo.getIntoBelongId()));
        }
        RepairInfoListQueryBO param = new RepairInfoListQueryBO();
        param.setRepairId(repairId);
        List<RepairInfoDO> infoList = repairInfoService.search(param);
        vo.setInfoList(infoList);
        return vo;
    }

    /**
     * 保存草稿
     *
     * @param dto
     */
    @Transactional
    public void saveDraft(RepairTicketDTO dto) {
        logs.info("【保存草稿】草稿信息:{}", dto);

        LoginInfo user = tokenService.getUser();
        Long belongId = user.getBelongId();
        logs.info("【保存草稿】当前用户所属ID:{}", belongId);
        Assert.isTrue(BeanUtils.isNotNull(belongId), ErrorEnum.BUSINESS_121003.getText());

        RepairTicketDO repairTicket = new RepairTicketDO();
        BeanUtils.clone(dto, repairTicket);
        String repairCode = UUIDUtils.repairCode();
        logs.info("【保存草稿】坏返单号:{}", repairCode);

        Integer repairStatus = RepairStatus.DRAFT.getCode();

        // 删除当前用户之前的草稿
        RepairTicketDO delete = new RepairTicketDO();
        delete.setBelongId(belongId);
        delete.setRepairStatus(repairStatus);
        repairTicketService.deleteByTicket(new RepairRemoveBO(belongId, repairStatus));

        repairTicket.setBelongId(belongId);
        repairTicket.setRepairStatus(repairStatus);
        repairTicket.setRepairCode(repairCode);
        Assert.isTrue(repairTicketService.create(repairTicket), "新增失败");

        Long repairId = repairTicket.getRepairId();
        logs.info("【保存草稿】坏返单ID:{}", repairId);

        // 处理坏返单详情
        if (BeanUtils.isNotNull(dto.getInfoList())) {
            handleInfoList(repairTicket, dto.getInfoList(), false);
        }
    }

    /**
     * 获取草稿
     *
     * @param belongId
     * @return
     */
    public RepairTicketVO getDraft(Long belongId) {

        RepairTicketDO ticket = repairTicketService.select(new RepairSelectQueryBO(belongId, RepairStatus.DRAFT.getCode()));
        RepairTicketVO vo = new RepairTicketVO();
        if (BeanUtils.isNotNull(ticket)) {
            BeanUtils.clone(ticket, vo);
        }

        Long repairId = vo.getRepairId();
        logs.info("【获取草稿】坏返单ID:{}", repairId);

        if (BeanUtils.isNotNull(repairId)) {
            RepairInfoListQueryBO param = new RepairInfoListQueryBO();
            param.setRepairId(vo.getRepairId());
            List<RepairInfoDO> infoList = repairInfoService.search(param);
            vo.setInfoList(infoList);
            vo.setDraftStatus(DraftStatus.EXIST.getCode());
        } else {
            vo.setDraftStatus(DraftStatus.ABSENT.getCode());
        }

        return vo;
    }

    /**
     * @param dto
     * @Title audit
     * @Desc 审核
     * @Date 2024-08-29 15:28:37.016
     */
    @Transactional
    public void audit(RepairAuditDTO dto) {
        Long repairId = dto.getRepairId();
        Integer auditStatus = dto.getAuditStatus();
        logs.info("【审核坏返单】坏返ID:{}", repairId);
        logs.info("【审核坏返单】审核状态:{}", auditStatus);
        Assert.isTrue(BeanUtils.isNotNull(repairId), ErrorEnum.CHECKED_811021.getText());
        Assert.isTrue(BeanUtils.isNotNull(auditStatus), ErrorEnum.CHECKED_811022.getText());

        LoginInfo user = tokenService.getUser();
        Long belongId = user.getBelongId();
        logs.info("【审核坏返单】当前用户所属ID:{}", belongId);
        Assert.isTrue(BeanUtils.isNotNull(belongId), ErrorEnum.BUSINESS_121003.getText());

        BelongDO belongVO = BaseCache.getBelong(belongId);
        logs.info("【审核坏返单】当前用户所属信息:{}", belongVO);
        Assert.isTrue(BeanUtils.isNotNull(belongVO), ErrorEnum.BUSINESS_121004.getText());

        logs.info("【审核坏返单】坏返单ID:{}", repairId);
        RepairTicketDO ticket = repairTicketService.select(repairId);
        logs.info("【审核坏返单】坏返单信息:{}", ticket);
        Assert.isTrue(BeanUtils.isNotNull(ticket), ErrorEnum.BUSINESS_812007.getText());
        Assert.isTrue(Objects.equals(AuditStatus.WAIT.getCode(), ticket.getAuditStatus()), ErrorEnum.BUSINESS_812005.getText());

        RepairTicketDO update = new RepairTicketDO();
        update.setRepairId(repairId);
        update.setAuditStatus(auditStatus);

        RepairInfoListQueryBO param = new RepairInfoListQueryBO();
        param.setRepairId(repairId);
        List<RepairInfoDO> infoList = repairInfoService.search(param);
        ticket.set("infoList", infoList);

        Integer handleType = dto.getHandleType();
        Long intoBelongId = dto.getIntoBelongId();
        logs.info("【审核坏返单】处理方式:{}", handleType);
        logs.info("【审核坏返单】入库单位:{}", intoBelongId);
        update.setHandleType(handleType);


        if (Objects.equals(AuditStatus.ACCEPT.getCode(), auditStatus)) {
            Assert.isTrue(BeanUtils.isNotNull(handleType), ErrorEnum.CHECKED_811020.getText());
            if (Objects.equals(RepairType.DISCARD.getCode(), handleType)) {
                // 报废直接出库单 已完成
                update.setRepairStatus(RepairStatus.FINISH.getCode());
                // 生成报废单
                DiscardTicketDO discardTicket = handleDiscardTicket(ticket, user, belongVO);
                // 关联报废单
                update.setDiscardId(discardTicket.getDiscardId());
                update.setDiscardCode(discardTicket.getDiscardCode());
            } else {
                Assert.isTrue(BeanUtils.isNotNull(intoBelongId), ErrorEnum.CHECKED_811019.getText());
                ticket.setIntoBelongId(dto.getIntoBelongId());
                update.setRepairStatus(RepairStatus.WAIT_INTO_STORAGE.getCode());
                // 处理出库单据
                handleRepairStorageTicket(ticket, infoList, StorageType.OUT_STORAGE.getCode());
                // 处理入库单据
                handleRepairStorageTicket(ticket, infoList, StorageType.INTO_STORAGE.getCode());
                update.setIntoBelongId(intoBelongId);
            }
        } else {
            // 审核驳回 返还库存
            backStock(ticket.getOutBelongId(), infoList);
            if (BeanUtils.isNotNull(dto.getReason())) {
                update.setReason(dto.getReason());
            }
            update.setRepairStatus(RepairStatus.CANCEL.getCode());
        }

        StorageUpdateAuditBO auditBO = new StorageUpdateAuditBO();
        Date time = TimeUtils.getNowDate();
        auditBO.setBusinessId(repairId);
        auditBO.setAuditStatus(auditStatus);
        auditBO.setAuditTime(time);
        auditBO.setAuditId(user.getUserId());
        auditBO.setAuditName(user.getNickname());
        auditBO.setAuditBelongId(belongVO.getBelongId());
        auditBO.setAuditBelongName(belongVO.getBelongName());
        Assert.isTrue(repairTicketService.updateAuditStatus(auditBO));
        Assert.isTrue(repairTicketService.update(update), "修改失败");
    }

    /**
     * @param repairId 坏返ID
     * @Title cancel
     * @Desc 取消坏返单
     * @Date 2024-08-29 17:24:40.626
     */
    @Transactional
    public void cancel(Long repairId) {
        // 待审核报废单可取消
        RepairTicketDO ticket = repairTicketService.select(repairId);
        logs.info("【取消坏返单】坏返单信息:{}", ticket);
        Assert.isTrue(BeanUtils.isNotNull(ticket), ErrorEnum.BUSINESS_812007.getText());

        Integer repairStatus = ticket.getRepairStatus();
        Assert.isTrue(BeanUtils.equals(repairStatus, RepairStatus.COMMIT.getCode(), RepairStatus.WAIT_INTO_STORAGE.getCode()), "当前状态不能取消坏返");
        Integer auditStatus = ticket.getAuditStatus();
        Assert.isTrue(BeanUtils.equals(auditStatus, AuditStatus.WAIT.getCode(), AuditStatus.ACCEPT.getCode()), "当前状态不能取消坏返");

        // 取消报废单
        RepairTicketDO repairTicket = new RepairTicketDO();
        repairTicket.setRepairId(repairId);
        if (Objects.equals(AuditStatus.WAIT.getCode(), auditStatus) && Objects.equals(RepairStatus.COMMIT.getCode(), repairStatus)) {
            RepairTicketDO reset = new RepairTicketDO();
            reset.setAuditStatus(auditStatus);
            reset.setRepairId(repairId);
            repairTicketService.resetAuditStatus(repairId);
        }
        repairTicket.setRepairStatus(RepairStatus.CANCEL.getCode());
        repairTicketService.update(repairTicket);

        // 已提交  不可用库存回滚为可用库存  待入库 直接增加可用库存
        RepairInfoListQueryBO param = new RepairInfoListQueryBO();
        param.setRepairId(repairId);
        List<RepairInfoDO> infoList = repairInfoService.search(param);

        if (Objects.equals(RepairStatus.COMMIT.getCode(), repairStatus)) {
            backStock(ticket.getOutBelongId(), infoList);
        } else {
            RollbackDTO backDto = new RollbackDTO();
            backDto.setBusinessType(StorageBusinessType.REPAIR_BUSINESS.getCode());
            backDto.setBusinessCode(ticket.getRepairCode());
            backDto.setBusinessStatus(RepairStatus.CANCEL.getCode());
            interactBusiness.rollback(backDto);
        }


    }

    /**
     * @param dto 坏返单DTO
     * @Title commit
     * @Desc 重新提交坏返单
     * @Date 2024-08-29 18:17:19.089
     */
    @Transactional
    public void commit(RepairTicketDTO dto) {
        // 草稿重新提交 就是修改报废单并提交
        logs.info("【重新提交坏返单】报废单信息:{}", dto);
        checkRepairTicket(dto);

        Long repairId = dto.getRepairId();
        Assert.isTrue(BeanUtils.isNotNull(repairId), "未找到坏返单ID");

        Integer repairStatus = dto.getRepairStatus();
        logs.info("【重新提交坏返单】坏返单状态:{}", repairStatus);
        Assert.isTrue(BeanUtils.equals(repairStatus, RepairStatus.DRAFT.getCode(), RepairStatus.CANCEL.getCode()), "当前状态不可提交");

        LoginInfo user = tokenService.getUser();
        Long userId = user.getUserId();
        String userType = user.getUserType();
        Long belongId = user.getBelongId();
        logs.info("【重新提交坏返单】当前用户ID:{},当前用户类型:{},当前用户所属ID:{}", userId, userType, belongId);
        Assert.isTrue(BeanUtils.isNotNull(belongId), ErrorEnum.BUSINESS_121003.getText());


        BelongDO belongVO = BaseCache.getBelong(belongId);
        logs.info("【重新提交坏返单】当前用户所属信息:{}", belongVO);
        Assert.isTrue(BeanUtils.isNotNull(belongVO), ErrorEnum.BUSINESS_121004.getText());

        RepairTicketDO repairTicket = new RepairTicketDO();

        Date time = TimeUtils.getNowDate();
        repairTicket.setRepairId(repairId);
        repairTicket.setRepairCode(dto.getRepairCode());
        repairTicket.setBelongId(dto.getBelongId());
        repairTicket.setOutBelongId(dto.getOutBelongId());
        repairTicket.setAlbumPics(dto.getAlbumPics());
        repairTicket.setBelongId(belongId);
        repairTicket.setApplyId(userId);
        repairTicket.setApplyName(user.getNickname());
        repairTicket.setApplyTime(time);
        repairTicket.setApplyBelongId(belongVO.getBelongId());
        repairTicket.setApplyBelongName(belongVO.getBelongName());
        repairTicket.setRepairStatus(RepairStatus.COMMIT.getCode());
        repairTicket.setRemark(dto.getRemark());

        Integer auditStatus = dto.getAuditStatus();
        logs.info("【重新提交坏返单】审核状态:{}", auditStatus);
        if (Objects.equals(RepairStatus.CANCEL.getCode(), repairStatus) && BeanUtils.isNotNull(auditStatus) && BeanUtils.equals(auditStatus, AuditStatus.ACCEPT.getCode(), AuditStatus.REJECT.getCode())) {
            String repairCode = UUIDUtils.repairCode();
            repairTicket.setCreateTime(time);
            repairTicket.setRepairCode(repairCode);
            handleCancelTicket(dto, repairTicket);
        } else {
            Assert.isTrue(repairTicketService.update(repairTicket), "修改失败");
            handleInfoList(repairTicket, dto.getInfoList(), true);
            StorageUpdateAuditBO auditBO = new StorageUpdateAuditBO();
            auditBO.setBusinessId(repairId);
            auditBO.setAuditStatus(AuditStatus.WAIT.getCode());
            repairTicketService.updateAuditStatus(auditBO);
        }
    }

    /**
     * @param repairIds 坏返ID
     * @Title delete
     * @Desc 删除坏返单
     * @Date 2024-08-30 09:19:01.486
     */
    @Transactional
    public void delete(Long... repairIds) {
        repairTicketService.deleteDraft(repairIds);
        repairInfoService.deleteByRepairIds(repairIds);
    }

    /*--------------------------------------------处理/参数校验------------------------------------*/

    /**
     * 处理坏返单详情
     */
    private void handleInfoList(RepairTicketDO repairTicket, List<RepairInfoDO> infoList, boolean checkStatus) {
        // 先查出来所有  没有就新增 有就修改  其他删除
        RepairInfoListQueryBO param = new RepairInfoListQueryBO();
        param.setRepairId(repairTicket.getRepairId());
        List<RepairInfoDO> list = repairInfoService.search(param);
        logs.info("【处理报废单详情】存在的详情:{}", list);

        List<RepairInfoDO> createList = new ArrayList<>();
        List<RepairInfoDO> updateList = new ArrayList<>();
        List<Long> deleteIds = new ArrayList<>();

        // 获取当前详情
        for (RepairInfoDO allocateInfo : list) {
            deleteIds.add(allocateInfo.getInfoId());
        }

        // 处理详情
        for (RepairInfoDO repairInfo : infoList) {
            repairInfo.setBelongId(repairTicket.getBelongId());
            repairInfo.setRepairId(repairTicket.getRepairId());
            repairInfo.setRepairCode(repairTicket.getRepairCode());

            // 非草稿状态都需要检验
            if (checkStatus) {
                checkRepairInfo(repairInfo);
                checkStock(repairTicket, repairInfo);
            }
            // 进行修改的详情
            Long infoId = repairInfo.getInfoId();
            logs.info("【处理坏返单详情】详情ID:{}", infoId);
            if (BeanUtils.isNotNull(repairInfo.getInfoId())) {
                // 进行修改的剔除删除行列
                updateList.add(repairInfo);
                if (deleteIds.contains(infoId)) {
                    deleteIds.remove(infoId);
                }
            } else {
                createList.add(repairInfo);
            }
        }

        Assert.isTrue(repairInfoService.delete(deleteIds), "删除失败");

        logs.info("【处理坏返单详情】新增坏返单详情:{}", createList);
        for (RepairInfoDO create : createList) {
            Assert.isTrue(repairInfoService.create(create), "新增失败");
        }

        logs.info("【处理坏返单详情】修改坏返单详情:{}", updateList);
        for (RepairInfoDO update : updateList) {
            repairInfoService.update(update);
        }
    }

    /**
     * 处理报废出库单据
     */
    public void handleRepairStorageTicket(RepairTicketDO repairTicket, List<RepairInfoDO> infoList, Integer storageType) {

        StorageTicketDO storageTicket = new StorageTicketDO();
        List<StorageRecordsDO> recordsList = new ArrayList<>();

        Long repairId = repairTicket.getRepairId();
        logs.info("【处理出入库单据】业务ID:{}", repairId);

        String repairCode = repairTicket.getRepairCode();
        logs.info("【处理出入库单据】业务单号:{}", repairCode);

        Integer businessType = StorageBusinessType.REPAIR_BUSINESS.getCode();
        logs.info("【处理出入库单据】业务类型:{}", businessType);

        //库存操作参数
        StorageOperateDTO operateDTO = new StorageOperateDTO();
        List<StockDTO> dtoList = new ArrayList<>();

        storageTicket.setBusinessId(repairId);
        storageTicket.setBusinessCode(repairCode);
        storageTicket.setBusinessType(businessType);
        storageTicket.setStorageType(storageType);
        storageTicket.setDeletable(DeletableStatus.CAN_NOT.getCode());

        if (Objects.equals(StorageType.INTO_STORAGE.getCode(), storageType)) {
            String ticketCode = UUIDUtils.intoStorageCode();
            logs.info("【处理出入库单据】入库单据Code:{}", ticketCode);

            Long intoBelongId = repairTicket.getIntoBelongId();
            logs.info("【处理出入库单据】入库单位:{}", intoBelongId);
            storageTicket.setTicketCode(ticketCode);
            storageTicket.setBelongId(intoBelongId);
        } else {
            String ticketCode = UUIDUtils.outStorageCode();
            logs.info("【处理出入库单据】出库据Code:{}", ticketCode);

            Long outBelongId = repairTicket.getOutBelongId();
            logs.info("【处理出入库单据】出库单位:{}", outBelongId);

            operateDTO.setBelongId(outBelongId);
            operateDTO.setStorageType(storageType);
            operateDTO.setBusinessType(StorageBusinessType.REPAIR_BUSINESS.getCode());
            operateDTO.setBusinessCode(repairCode);

            storageTicket.setOperateTime(TimeUtils.getNowDate());
            storageTicket.setOperateName(SystemName.ENABLED.getText());
            storageTicket.setTicketCode(ticketCode);
            storageTicket.setStorageStatus(StorageStatus.ALREADY_STORAGE.getCode());
            storageTicket.setBelongId(outBelongId);
        }

        logs.info("【处理出入库单据】出入库单据信息:{}", storageTicket);
        Assert.isTrue(storageTicketService.create(storageTicket), "新增失败");

        for (RepairInfoDO info : infoList) {
            StorageRecordsDO storageRecords = new StorageRecordsDO();

            BeanUtils.clone(info, storageRecords);
            BeanUtils.clone(storageTicket, storageRecords);

            BigDecimal repairAmount = info.getRepairAmount();
            logs.info("【处理出入库单据】坏返数量:{}", repairAmount);
            storageRecords.setExpectQuantity(repairAmount);
            if (Objects.equals(StorageType.OUT_STORAGE.getCode(), storageType)) {
                storageRecords.setActualQuantity(repairAmount);
                storageRecords.setOperateTime(TimeUtils.getNowDate());
            }

            StockDTO stockDTO = new StockDTO();
            stockDTO.setProductId(info.getProductId());
            stockDTO.setActualQuantity(repairAmount);

            recordsList.add(storageRecords);
            dtoList.add(stockDTO);

        }

        logs.info("【处理出入库单据】出入库记录:{}", recordsList);
        for (StorageRecordsDO storageRecords : recordsList) {
            Assert.isTrue(storageRecordsService.create(storageRecords), "新增失败");
        }

        if (Objects.equals(StorageType.OUT_STORAGE.getCode(), storageType)) {
            operateDTO.setList(dtoList);
            interactBusiness.operateStorage(operateDTO);
        }
    }

    /**
     * 检查库存
     *
     * @param info
     */
    private void checkStock(RepairTicketDO repairTicket, RepairInfoDO info) {
        Long belongId = repairTicket.getOutBelongId();
        Long productId = info.getProductId();
        BigDecimal repairAmount = info.getRepairAmount();

        Integer stockStatus = stockConsumer.getStockStatus(belongId);

        //变更库存
        if (Objects.equals(LogicCode.YES, stockStatus)) {
            StockDO stock = new StockDO();
            List<StockDO> stockList = new ArrayList<>();
            stock.setBelongId(belongId);
            stock.setProductId(productId);
            stock.setUsableStock(repairAmount.negate());
            stock.setDisableStock(repairAmount);
            stock.setAllStock(BigDecimal.ZERO);
            stock.setFrozenStock(BigDecimal.ZERO);
            stockList.add(stock);
            stockProvide.handleStock(stockList);
        }
    }

    /**
     * 返还库存
     *
     * @param belongId
     * @param infoList
     */
    private void backStock(Long belongId, List<RepairInfoDO> infoList) {
        Integer stockStatus = stockConsumer.getStockStatus(belongId);
        if (Objects.equals(LogicCode.YES, stockStatus)) {
            List<StockDO> stockList = new ArrayList<>();
            for (RepairInfoDO repairInfo : infoList) {
                StockDO stock = new StockDO();
                stock.setBelongId(belongId);
                stock.setProductId(repairInfo.getProductId());
                stock.setDisableStock(repairInfo.getRepairAmount().negate());
                stock.setUsableStock(repairInfo.getRepairAmount());
                stock.setAllStock(BigDecimal.ZERO);
                stock.setFrozenStock(BigDecimal.ZERO);
                stockList.add(stock);
            }
            stockProvide.handleStock(stockList);
        }
    }

    /**
     * 处理报废单
     *
     * @param belongVO
     * @param user
     */
    private DiscardTicketDO handleDiscardTicket(RepairTicketDO ticket, LoginInfo user, BelongDO belongVO) {
        // 报废单进行赋值
        DiscardTicketDO discardTicket = new DiscardTicketDO();

        BeanUtils.clone(ticket, discardTicket);

        String discardCode = UUIDUtils.discardCode();
        logs.info("【处理报废单】报废单号:{}", discardCode);
        discardTicket.setDiscardStatus(DiscardStatus.FINISH.getCode());
        Date time = TimeUtils.getNowDate();
        logs.info("【处理报废单】提交时间:{}", time);
        discardTicket.setApplyTime(time);
        discardTicket.setAuditTime(time);

        discardTicket.setCreateTime(time);
        discardTicket.setDiscardCode(discardCode);

        discardTicket.setAuditStatus(AuditStatus.ACCEPT.getCode());
        discardTicket.setAuditBelongId(belongVO.getBelongId());
        discardTicket.setAuditBelongName(belongVO.getBelongName());
        discardTicket.setAuditId(user.getUserId());
        discardTicket.setAuditName(user.getNickname());

        // 新增报废单
        Assert.isTrue(discardTicketService.create(discardTicket), "新增失败");

        List<RepairInfoDO> infoList = ticket.get("infoList");
        Assert.isTrue(BeanUtils.isNotNull(infoList), ErrorEnum.BUSINESS_812008.getText());

        List<DiscardInfoDO> discardInfoList = new ArrayList<>();
        for (RepairInfoDO repairInfo : infoList) {
            DiscardInfoDO discardInfo = new DiscardInfoDO();
            BeanUtils.clone(repairInfo, discardInfo);
            discardInfo.setDiscardId(discardTicket.getDiscardId());
            discardInfo.setDiscardCode(discardTicket.getDiscardCode());
            discardInfo.setDiscardAmount(repairInfo.getRepairAmount());
            // 校验库存
            // 后续加上 business.checkDiscardStock
            discardInfo.setInfoId(null);
            Assert.isTrue(discardInfoService.create(discardInfo), "新增失败");
            discardInfoList.add(discardInfo);
        }
        // 处理出入库单据
        business.handleDiscardStorageTicket(discardTicket, discardInfoList);

        return discardTicket;
    }

    /**
     * @param dto          坏返单参数
     * @param repairTicket
     * @Title handleCancelTicket
     * @Desc 处理取消状态坏返单
     * @Date 2024-08-29 18:38:28.619
     */
    private void handleCancelTicket(RepairTicketDTO dto, RepairTicketDO repairTicket) {
        Long repairId = dto.getRepairId();
        logs.info("【处理取消状态坏返单】单据ID:{}", repairId);
        Integer repairStatus = RepairStatus.SCRAP.getCode();
        RepairTicketDO update = new RepairTicketDO();
        update.setRepairId(repairId);
        update.setRepairStatus(repairStatus);
        Assert.isTrue(repairTicketService.update(update), "修改失败");

        repairTicket.setRepairId(null);
        Assert.isTrue(repairTicketService.create(repairTicket), "新增失败");
        StorageUpdateAuditBO auditBO = new StorageUpdateAuditBO();
        auditBO.setBusinessId(repairId);
        auditBO.setAuditStatus(AuditStatus.CANCEL.getCode());
        repairTicketService.updateAuditStatus(auditBO);

        StorageUpdateAuditBO auditBO1 = new StorageUpdateAuditBO();
        auditBO1.setBusinessId(repairTicket.getRepairId());
        auditBO1.setAuditStatus(AuditStatus.WAIT.getCode());
        repairTicketService.updateAuditStatus(auditBO1);

        List<RepairInfoDO> infoList = dto.getInfoList();
        logs.info("【处理取消状态坏返单】商品信息:{}", infoList);

        List<RepairInfoDO> createList = new ArrayList<>();

        for (RepairInfoDO repairInfo : infoList) {
            checkRepairInfo(repairInfo);
            RepairInfoDO info = new RepairInfoDO();
            BeanUtils.clone(repairInfo, info);

            info.setInfoId(null);
            info.setRepairId(repairTicket.getRepairId());
            info.setRepairCode(repairTicket.getRepairCode());
            checkStock(repairTicket, info);
            createList.add(info);
        }

        for (RepairInfoDO create : createList) {
            Assert.isTrue(repairInfoService.create(create), "新增失败");
        }
    }

    /**
     * 校验坏返参数
     *
     * @param dto
     */
    private void checkRepairTicket(RepairTicketDTO dto) {
        Long outBelongId = dto.getOutBelongId();
        List<RepairInfoDO> infoList = dto.getInfoList();
        String albumPics = dto.getAlbumPics();

        logs.info("【参数校验】出库单位:{}", outBelongId);
        logs.info("【参数校验】商品详情:{}", infoList);
        logs.info("【参数校验】坏返照片:{}", albumPics);

        Assert.isTrue(BeanUtils.isNotNull(outBelongId), ErrorEnum.CHECKED_811016.getText());
        Assert.isTrue(BeanUtils.isNotNull(infoList), ErrorEnum.CHECKED_811003.getText());
        Assert.isTrue(BeanUtils.isNotNull(albumPics), ErrorEnum.CHECKED_811017.getText());
    }

    /**
     * 校验坏返详情参数
     */
    private void checkRepairInfo(RepairInfoDO dto) {
        Long productId = dto.getProductId();
        String productSku = dto.getProductSku();
        String productName = dto.getProductName();
        BigDecimal repairAmount = dto.getRepairAmount();
        Long unitId = dto.getUnitId();

        logs.info("【商品参数校验】商品ID:{}", productId);
        logs.info("【商品参数校验】商品sku:{}", productSku);
        logs.info("【商品参数校验】商品名称:{}", productName);
        logs.info("【商品参数校验】坏返数量:{}", repairAmount);
        logs.info("【商品参数校验】商品单位:{}", unitId);

        Assert.isTrue(BeanUtils.isNotNull(productId), ErrorEnum.CHECKED_811003.getText());
        Assert.isTrue(BeanUtils.isNotNull(productSku), ErrorEnum.CHECKED_811003.getText());
        Assert.isTrue(BeanUtils.isNotNull(productName), ErrorEnum.CHECKED_811003.getText());
        Assert.isTrue(BeanUtils.isNotNull(repairAmount), ErrorEnum.CHECKED_811018.getText());
        Assert.isTrue(BeanUtils.isNotNull(unitId), ErrorEnum.CHECKED_811003.getText());
        Assert.isTrue(DecimalUtils.more(repairAmount, BigDecimal.ZERO), ErrorEnum.CHECKED_811012.getText());

    }

}